package com.traffic.between.util;

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public final class SecurityUtil {

	public SecurityUtil() {
	}

	public static byte[] getDigestSHA(String source) throws Exception {
		return getDigestSHA(source.getBytes("UTF8"));
	}

	public static byte[] getDigestSHA(String source, String charset) throws Exception {
		return getDigestSHA(source.getBytes(charset));
	}

	public static byte[] getDigestSHA(byte source[]) throws Exception {
		MessageDigest thisMD = MessageDigest.getInstance("SHA");
		byte digest[] = thisMD.digest(source);
		return digest;
	}

	public static String shaEncoding(byte source[]) throws Exception {
		return encodeHex(getDigestSHA(source));
	}

	public static String shaEncoding(String source) throws Exception {
		return encodeHex(getDigestSHA(source));
	}

	public static String shaEncoding(String source, String charset) throws Exception {
		return encodeHex(getDigestSHA(source, charset));
	}

	public static byte[] getDigestMD5(String source) throws Exception {
		return getDigestMD5(source, "UTF8");
	}

	public static byte[] getDigestMD5(String source, String charset) throws Exception {
		return getDigestMD5(source.getBytes(charset));
	}

	public static byte[] getDigestMD5(byte source[]) throws Exception {
		MessageDigest thisMD = MessageDigest.getInstance("MD5");
		return thisMD.digest(source);
	}

	public static String md5encoding(String source) throws Exception {
		return encodeHex(getDigestMD5(source));
	}

	public static String md5encoding(String source, String charset) throws Exception {
		return encodeHex(getDigestMD5(source, charset));
	}

	public static String md5encoding(byte source[]) throws Exception {
		return encodeHex(getDigestMD5(source));
	}

	public static final String encodeHex(byte bytes[]) {
		StringBuffer buf = new StringBuffer(bytes.length * 2);
		for (int i = 0; i < bytes.length; i++) {
			if ((bytes[i] & 255) < 16)
				buf.append("0");
			buf.append(Long.toString(bytes[i] & 255, 16));
		}

		return buf.toString();
	}

	public static final byte[] encryptAESByCBC(String sKey, String ivParam, String sSrc) throws Exception {
		return encryptAESByCBC(sKey, ivParam.getBytes(), sSrc);
	}

	public static final byte[] encryptAESByCBC(String sKey, byte ivParam[], String sSrc) throws Exception {
		return encryptAESByCBC(sKey.getBytes(), ivParam, sSrc);
	}

	public static final byte[] encryptAESByCBC(byte keyBytes[], byte ivBytes[], String sSrc) throws Exception {
		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
		SecretKeySpec skeySpec = new SecretKeySpec(keyBytes, "AES");
		IvParameterSpec iv = new IvParameterSpec(ivBytes);
		cipher.init(1, skeySpec, iv);
		byte encrypted[] = cipher.doFinal(sSrc.getBytes("utf-8"));
		return encrypted;
	}

	public static final String decryptAESByCBC(String sKey, String ivParam, byte encrBytes[]) throws Exception {
		return decryptAESByCBC(sKey, ivParam.getBytes(), encrBytes);
	}

	public static final String decryptAESByCBC(String sKey, byte ivBytes[], byte encrBytes[]) throws Exception {
		return decryptAESByCBC(sKey.getBytes("ASCII"), ivBytes, encrBytes);
	}

	public static final String decryptAESByCBC(byte keyBytes[], byte ivBytes[], byte encrBytes[]) throws Exception {
		SecretKeySpec skeySpec = new SecretKeySpec(keyBytes, "AES");
		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
		IvParameterSpec iv = new IvParameterSpec(ivBytes);
		cipher.init(2, skeySpec, iv);
		byte original[] = cipher.doFinal(encrBytes);
		String originalString = new String(original, "utf-8");
		return originalString;
	}

	public static KeyPair genKey() throws Exception {
		long mySeed = System.currentTimeMillis();
		KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
		SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
		random.setSeed(mySeed);
		keyGen.initialize(1024, random);
		KeyPair keyPair = keyGen.generateKeyPair();
		return keyPair;
	}

	public static byte[] encryptByRSA(byte pubKeyInByte[], byte data[]) throws Exception {
		KeyFactory mykeyFactory = KeyFactory.getInstance("RSA");
		X509EncodedKeySpec pub_spec = new X509EncodedKeySpec(pubKeyInByte);
		java.security.PublicKey pubKey = mykeyFactory.generatePublic(pub_spec);
		Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
		cipher.init(1, pubKey);
		return cipher.doFinal(data);
	}

	public static byte[] encryptByRSA(byte pubKeyInByte[], String data) throws Exception {
		return encryptByRSA(pubKeyInByte, data.getBytes("UTF8"));
	}

	public static byte[] decryptByRSA(byte privKeyInByte[], byte data[]) throws Exception {
		PKCS8EncodedKeySpec priv_spec = new PKCS8EncodedKeySpec(privKeyInByte);
		KeyFactory mykeyFactory = KeyFactory.getInstance("RSA");
		java.security.PrivateKey privKey = mykeyFactory.generatePrivate(priv_spec);
		Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
		cipher.init(2, privKey);
		return cipher.doFinal(data);
	}

	public static byte[] decryptByRSA(byte privKeyInByte[], String data) throws Exception {
		return decryptByRSA(privKeyInByte, data.getBytes("UTF8"));
	}

	public static byte[] encodeAES(byte content[], String password) throws Exception {
		KeyGenerator kgen = KeyGenerator.getInstance("AES");
		SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
		random.setSeed(password.getBytes());
		kgen.init(128, random);
		SecretKey secretKey = kgen.generateKey();
		byte enCodeFormat[] = secretKey.getEncoded();
		SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
		Cipher cipher = Cipher.getInstance("AES");
		cipher.init(1, key);
		byte result[] = cipher.doFinal(content);
		return result;
	}

	public static String parseByte2HexStr(byte buf[]) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < buf.length; i++) {
			String hex = Integer.toHexString(buf[i] & 255);
			if (hex.length() == 1)
				hex = (new StringBuilder(String.valueOf('0'))).append(hex).toString();
			sb.append(hex.toUpperCase());
		}

		return sb.toString();
	}


//	private static final String algorithm_rsa = "RSA";
//	private static final String algorithm_aes = "AES";
//	private static final String algorithm_sha = "SHA";
//	private static final String algorithm_md5 = "MD5";
//	private static final String algorithm_des = "DESede";
//	private static final String _charset = "UTF8";
//	private static final String transformation = "RSA/ECB/PKCS1Padding";
}